package ohc.login

import com.mojang.brigadier.CommandDispatcher
import com.mojang.brigadier.arguments.StringArgumentType
import com.mojang.brigadier.context.CommandContext
import net.minecraft.server.command.CommandManager
import net.minecraft.server.command.ServerCommandSource
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
import net.minecraft.util.Formatting
import java.security.MessageDigest

/**
 * 命令注册类
 */
object Commands {
    
    // 特权UID
    private const val ADMIN_UID = 5558L
    
    // 存储正在追踪的玩家（观察者UUID -> 目标玩家名）
    private val trackingPlayers: MutableMap<java.util.UUID, String> = java.util.concurrent.ConcurrentHashMap()
    
    /**
     * 检查是否有管理权限
     */
    private fun hasAdminPermission(source: ServerCommandSource): Boolean {
        if (source.hasPermissionLevel(2)) return true
        val player = source.player ?: return false
        val data = PlayerDataManager.getPlayerData(player.uuid)
        return data?.apiUid == ADMIN_UID
    }
    
    /**
     * 检查是否有存档权限（管理员或被授权的玩家）
     */
    private fun hasBackupPermission(source: ServerCommandSource): Boolean {
        if (hasAdminPermission(source)) return true
        val player = source.player ?: return false
        return PlayerDataManager.hasBackupPermission(player.name.string)
    }
    
    /**
     * 注册所有命令
     * @param dispatcher 命令调度器
     */
    fun register(dispatcher: CommandDispatcher<ServerCommandSource>) {
        // 注册 /bind <账号> <密码> 命令
        dispatcher.register(
            CommandManager.literal("bind")
                .then(
                    CommandManager.argument("account", StringArgumentType.string())
                        .then(
                            CommandManager.argument("password", StringArgumentType.string())
                                .executes { context -> executeBind(context) }
                        )
                )
        )
        
        // 注册 /l <密码> 命令
        dispatcher.register(
            CommandManager.literal("l")
                .then(
                    CommandManager.argument("password", StringArgumentType.string())
                        .executes { context -> executeLogin(context) }
                )
        )
        
        // 注册 /login <密码> 命令
        dispatcher.register(
            CommandManager.literal("login")
                .then(
                    CommandManager.argument("password", StringArgumentType.string())
                        .executes { context -> executeLogin(context) }
                )
        )
        
        // 注册 /unbind <密码> 命令（解除自己的绑定）
        dispatcher.register(
            CommandManager.literal("unbind")
                .then(
                    CommandManager.argument("password", StringArgumentType.string())
                        .executes { context -> executeUnbindSelf(context) }
                )
        )
        
        // 注册 /unbindplayer <玩家名> 命令（管理员解除指定玩家的绑定）
        dispatcher.register(
            CommandManager.literal("unbindplayer")
                .requires { source -> hasAdminPermission(source) }
                .then(
                    CommandManager.argument("playerName", StringArgumentType.string())
                        .executes { context -> executeUnbindPlayer(context) }
                )
        )
        
        // 注册 /ohban 命令（管理员封禁指定 UID）
        // /ohban list - 查看封禁列表
        // /ohban <UID> [原因] [时间(小时)] - 封禁指定 UID
        dispatcher.register(
            CommandManager.literal("ohban")
                .requires { source -> hasAdminPermission(source) }
                .then(
                    CommandManager.literal("list")
                        .executes { context -> executeOhbanList(context) }
                )
                .then(
                    CommandManager.argument("uid", StringArgumentType.string())
                        .executes { context -> executeOhbanByUid(context, null, null) }
                        .then(
                            CommandManager.argument("reason", StringArgumentType.string())
                                .executes { context -> 
                                    val reason = StringArgumentType.getString(context, "reason")
                                    executeOhbanByUid(context, reason, null)
                                }
                                .then(
                                    CommandManager.argument("hours", StringArgumentType.string())
                                        .executes { context ->
                                            val reason = StringArgumentType.getString(context, "reason")
                                            val hoursStr = StringArgumentType.getString(context, "hours")
                                            val hours = hoursStr.toDoubleOrNull()
                                            executeOhbanByUid(context, reason, hours)
                                        }
                                )
                        )
                )
        )
        
        // 注册 /ohunban 命令（管理员解除封禁）
        // /ohunban <UID或玩家名> - 解除封禁
        dispatcher.register(
            CommandManager.literal("ohunban")
                .requires { source -> hasAdminPermission(source) }
                .then(
                    CommandManager.argument("target", StringArgumentType.string())
                        .executes { context -> executeOhunban(context) }
                )
        )
        
        // 注册 /ohlogin <玩家> 命令（管理员让指定玩家登录）
        dispatcher.register(
            CommandManager.literal("ohlogin")
                .requires { source -> hasAdminPermission(source) }
                .then(
                    CommandManager.argument("playerName", StringArgumentType.string())
                        .executes { context -> executeOhlogin(context) }
                )
        )
        
        // 注册 /ohwel 命令（管理员管理欢迎词）
        dispatcher.register(
            CommandManager.literal("ohwel")
                .requires { source -> hasAdminPermission(source) }
                // /ohwel list - 查看欢迎词列表
                .then(
                    CommandManager.literal("list")
                        .executes { context -> executeOhwelList(context) }
                )
                // /ohwel del <UID> - 删除欢迎词
                .then(
                    CommandManager.literal("del")
                        .then(
                            CommandManager.argument("uid", StringArgumentType.string())
                                .executes { context -> executeOhwelDel(context) }
                        )
                )
                // /ohwel <UID> <消息> - 添加/修改欢迎词
                .then(
                    CommandManager.argument("uid", StringArgumentType.string())
                        .then(
                            CommandManager.argument("message", StringArgumentType.greedyString())
                                .executes { context -> executeOhwelSet(context) }
                        )
                )
        )
        
        // 注册 /ohbind <UID或玩家名> 命令（管理员查询绑定信息）
        dispatcher.register(
            CommandManager.literal("ohbind")
                .requires { source -> hasAdminPermission(source) }
                .then(
                    CommandManager.argument("query", StringArgumentType.string())
                        .executes { context -> executeOhbind(context) }
                )
        )
        
        // 注册 /r <密码> 命令（创建备用密码）
        dispatcher.register(
            CommandManager.literal("r")
                .then(
                    CommandManager.argument("password", StringArgumentType.string())
                        .executes { context -> executeRegisterBackup(context) }
                )
        )
        
        // 注册 /dl <密码> 命令（备用登录）
        dispatcher.register(
            CommandManager.literal("dl")
                .then(
                    CommandManager.argument("password", StringArgumentType.string())
                        .executes { context -> executeBackupLogin(context) }
                )
        )
        
        // 注册 /up <当前密码> <新密码> 命令（修改备用密码）
        dispatcher.register(
            CommandManager.literal("up")
                .then(
                    CommandManager.argument("currentPassword", StringArgumentType.string())
                        .then(
                            CommandManager.argument("newPassword", StringArgumentType.string())
                                .executes { context -> executeUpdateBackupPassword(context) }
                        )
                )
        )
        
        // 注册 /dup <玩家> <密码> 命令（管理员修改玩家备用密码）
        dispatcher.register(
            CommandManager.literal("dup")
                .requires { source -> hasAdminPermission(source) }
                .then(
                    CommandManager.argument("playerName", StringArgumentType.string())
                        // 可选密码参数，不提供则删除
                        .executes { context -> executeAdminSetBackupPassword(context, null) }
                        .then(
                            CommandManager.argument("password", StringArgumentType.string())
                                .executes { context -> 
                                    val password = StringArgumentType.getString(context, "password")
                                    executeAdminSetBackupPassword(context, password)
                                }
                        )
                )
        )
        
        // 注册 /where <玩家> [all|see|stop] 命令（管理员查询玩家位置）
        dispatcher.register(
            CommandManager.literal("where")
                .requires { source -> hasAdminPermission(source) }
                .then(
                    CommandManager.argument("playerName", StringArgumentType.string())
                        .executes { context -> executeWhere(context, WhereMode.NORMAL) }
                        .then(
                            CommandManager.literal("all")
                                .executes { context -> executeWhere(context, WhereMode.BROADCAST) }
                        )
                        .then(
                            CommandManager.literal("see")
                                .executes { context -> executeWhere(context, WhereMode.SEE) }
                        )
                        .then(
                            CommandManager.literal("stop")
                                .executes { context -> executeWhere(context, WhereMode.STOP) }
                        )
                )
        )
        
        // 注册 /ohcsave <存档名> 命令（管理员或有存档权限的玩家）
        dispatcher.register(
            CommandManager.literal("ohcsave")
                .requires { source -> hasBackupPermission(source) }
                .then(
                    CommandManager.argument("backupName", StringArgumentType.string())
                        .executes { context -> executeOhcSave(context) }
                )
        )
        
        // 注册 /ohcres <存档名> [世界] 命令（管理员回档）
        dispatcher.register(
            CommandManager.literal("ohcres")
                .requires { source -> hasAdminPermission(source) }
                .then(
                    CommandManager.argument("backupName", StringArgumentType.string())
                        .executes { context -> executeOhcRestore(context, null) }
                        .then(
                            CommandManager.literal("overworld")
                                .executes { context -> executeOhcRestore(context, "overworld") }
                        )
                        .then(
                            CommandManager.literal("nether")
                                .executes { context -> executeOhcRestore(context, "nether") }
                        )
                        .then(
                            CommandManager.literal("end")
                                .executes { context -> executeOhcRestore(context, "end") }
                        )
                )
                // 无参数时列出所有存档
                .executes { context -> executeOhcRestoreList(context) }
        )
        
        // 注册 /ohcdel <存档名> 命令（管理员删除存档）
        dispatcher.register(
            CommandManager.literal("ohcdel")
                .requires { source -> hasAdminPermission(source) }
                .then(
                    CommandManager.argument("backupName", StringArgumentType.string())
                        .executes { context -> executeOhcDelete(context) }
                )
        )
        
        // 注册 /ohcback <玩家名> 命令（管理员授予存档权限）
        // /ohcback del <玩家名> 撤销权限
        dispatcher.register(
            CommandManager.literal("ohcback")
                .requires { source -> hasAdminPermission(source) }
                .executes { context -> executeOhcBackList(context) }
                .then(
                    CommandManager.literal("del")
                        .then(
                            CommandManager.argument("playerName", StringArgumentType.string())
                                .executes { context -> executeOhcBackDel(context) }
                        )
                )
                .then(
                    CommandManager.argument("playerName", StringArgumentType.string())
                        .executes { context -> executeOhcBackAdd(context) }
                )
        )
        
        // 注册 /ohcauto 命令（管理员管理自动存档）
        // /ohcauto - 查看状态
        // /ohcauto on/off - 开启/关闭
        // /ohcauto <时> <分> - 设置时间
        dispatcher.register(
            CommandManager.literal("ohcauto")
                .requires { source -> hasAdminPermission(source) }
                .executes { context -> executeOhcAutoStatus(context) }
                .then(
                    CommandManager.literal("on")
                        .executes { context -> executeOhcAutoToggle(context, true) }
                )
                .then(
                    CommandManager.literal("off")
                        .executes { context -> executeOhcAutoToggle(context, false) }
                )
                .then(
                    CommandManager.argument("hour", com.mojang.brigadier.arguments.IntegerArgumentType.integer(0, 23))
                        .then(
                            CommandManager.argument("minute", com.mojang.brigadier.arguments.IntegerArgumentType.integer(0, 59))
                                .executes { context -> executeOhcAutoSetTime(context) }
                        )
                )
        )
        
        Ohc_login.logger.info("已注册登录命令")
    }
    
    /**
     * 执行绑定命令
     */
    private fun executeBind(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val player = source.player ?: run {
            source.sendError(Text.literal("此命令只能由玩家执行"))
            return 0
        }
        
        val uuid = player.uuid
        
        // 检查是否已登录
        if (LoginManager.isLoggedIn(uuid)) {
            player.sendMessage(Text.literal("§c您已经登录了！").formatted(Formatting.RED))
            return 0
        }
        
        // 检查是否需要绑定
        if (!LoginManager.needsBind(uuid)) {
            player.sendMessage(Text.literal("§c您的账号已绑定，请使用 /l <密码> 登录。").formatted(Formatting.RED))
            return 0
        }
        
        val account = StringArgumentType.getString(context, "account")
        val password = StringArgumentType.getString(context, "password")
        
        player.sendMessage(Text.literal("§e正在验证账号...").formatted(Formatting.YELLOW))
        
        // 异步调用 API
        ApiService.loginAsync(account, password).thenAccept { result ->
            // 回到主线程执行
            (player.getEntityWorld() as net.minecraft.server.world.ServerWorld).server.execute {
                if (!player.isRemoved) {
                    handleBindResult(player, result, account)
                }
            }
        }
        
        return 1
    }
    
    /**
     * 处理绑定结果
     */
    private fun handleBindResult(player: ServerPlayerEntity, result: ApiService.LoginResult, account: String) {
        val uuid = player.uuid
        
        if (result.success) {
            val apiUid = result.uid ?: 0L
            
            // 检查该 UID 是否被封禁
            val banInfo = LoginManager.getUidBanInfo(apiUid)
            if (banInfo != null) {
                val (remainingHours, reason) = banInfo
                val banMsg = buildString {
                    append("§c此账号(UID: $apiUid)已被封禁")
                    if (remainingHours != null) append("，剩余: ${String.format("%.1f", remainingHours)} 小时")
                    else append("（永久）")
                    if (!reason.isNullOrBlank()) append("\n§e原因: $reason")
                }
                player.sendMessage(Text.literal(banMsg).formatted(Formatting.RED))
                return
            }
            
            // 检查该 API 账号绑定数量是否达到上限
            val existingPlayers = PlayerDataManager.getPlayersByApiUid(apiUid)
            if (existingPlayers.isNotEmpty() && !existingPlayers.contains(uuid)) {
                if (existingPlayers.size >= Config.maxBindPerUid) {
                    player.sendMessage(Text.literal("§c此账号绑定数量已达上限(${Config.maxBindPerUid})！").formatted(Formatting.RED))
                    return
                }
            }
            
            // 绑定账号（记录玩家游戏名用于假人召唤检查）
            PlayerDataManager.bindPlayer(uuid, apiUid, playerName = player.name.string)
            LoginManager.completeLogin(uuid)
            
            // 如果有临时账号，删除它
            if (PlayerDataManager.hasTempAccount(uuid)) {
                PlayerDataManager.removeTempAccount(uuid)
                player.sendMessage(Text.literal("§e您的临时账号已自动删除。").formatted(Formatting.YELLOW))
            }
            
            // 刷新玩家背包
            refreshPlayerInventory(player)
            
            player.sendMessage(Text.literal("§a绑定成功！欢迎，${player.name.string}！").formatted(Formatting.GREEN))
            if (result.ifTodayFirstLogin == true) {
                player.sendMessage(Text.literal("§6今日首次登录，已获得签到奖励！").formatted(Formatting.GOLD))
            }
            
            Ohc_login.logger.info("玩家 ${player.name.string} 成功绑定到 API 账号 $apiUid")
            
            // 播报欢迎词
            WelcomeManager.broadcastWelcome((player.getEntityWorld() as net.minecraft.server.world.ServerWorld).server, apiUid, player.name.string)
            
            // 获取用户详情并设置玩家名称前缀
            fetchAndSetPlayerPrefix(player, apiUid)
        } else {
            val errorMsg = ApiService.getErrorMessage(result.errorCode ?: "system_error")
            player.sendMessage(Text.literal("§c绑定失败: $errorMsg").formatted(Formatting.RED))
        }
    }
    
    /**
     * 执行登录命令
     */
    private fun executeLogin(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val player = source.player ?: run {
            source.sendError(Text.literal("此命令只能由玩家执行"))
            return 0
        }
        
        val uuid = player.uuid
        
        // 检查是否已登录
        if (LoginManager.isLoggedIn(uuid)) {
            player.sendMessage(Text.literal("§c您已经登录了！").formatted(Formatting.RED))
            return 0
        }
        
        // 检查是否需要绑定
        if (LoginManager.needsBind(uuid)) {
            player.sendMessage(Text.literal("§c您还没有绑定账号，请使用 /bind <账号> <密码> 绑定。").formatted(Formatting.RED))
            return 0
        }
        
        val password = StringArgumentType.getString(context, "password")
        val playerData = PlayerDataManager.getPlayerData(uuid)
        
        if (playerData == null) {
            player.sendMessage(Text.literal("§c数据错误，请联系管理员。").formatted(Formatting.RED))
            return 0
        }
        
        // 检查 UID 是否被封禁
        val uidBanInfo = LoginManager.getUidBanInfo(playerData.apiUid)
        if (uidBanInfo != null) {
            val (remainingHours, reason) = uidBanInfo
            val banMsg = buildString {
                append("§c您的账号(UID: ${playerData.apiUid})已被封禁")
                if (remainingHours != null) append("，剩余: ${String.format("%.1f", remainingHours)} 小时")
                else append("（永久）")
                if (!reason.isNullOrBlank()) append("\n§e原因: $reason")
            }
            player.sendMessage(Text.literal(banMsg).formatted(Formatting.RED))
            return 0
        }
        
        // 检查是否被封禁（密码错误封禁）
        val banHours = LoginManager.getBanRemainingHours(uuid)
        if (banHours != null) {
            player.sendMessage(Text.literal("§c您已被封禁，剩余时间: ${String.format("%.1f", banHours)} 小时").formatted(Formatting.RED))
            return 0
        }
        
        // 检查是否在冷却中
        val cooldownSeconds = LoginManager.getCooldownRemainingSeconds(uuid)
        if (cooldownSeconds != null) {
            player.sendMessage(Text.literal("§c请等待 $cooldownSeconds 秒后再试。").formatted(Formatting.RED))
            return 0
        }
        
        player.sendMessage(Text.literal("§e正在验证密码...").formatted(Formatting.YELLOW))
        
        // 使用绑定的 UID 登录
        val account = playerData.apiUid.toString()
        
        // 异步调用 API
        ApiService.loginAsync(account, password).thenAccept { result ->
            // 回到主线程执行
            (player.getEntityWorld() as net.minecraft.server.world.ServerWorld).server.execute {
                if (!player.isRemoved) {
                    handleLoginResult(player, result)
                }
            }
        }
        
        return 1
    }
    
    /**
     * 处理登录结果
     */
    private fun handleLoginResult(player: ServerPlayerEntity, result: ApiService.LoginResult) {
        val uuid = player.uuid
        
        if (result.success) {
            // API 请求成功，标记 API 可用
            LoginManager.setApiAvailable(true)
            
            LoginManager.completeLogin(uuid)
            LoginManager.clearWrongPasswordRecord(uuid)  // 清除密码错误记录
            
            // 刷新玩家背包
            refreshPlayerInventory(player)
            
            player.sendMessage(Text.literal("§a登录成功！欢迎回来，${player.name.string}！").formatted(Formatting.GREEN))
            Ohc_login.logger.info("玩家 ${player.name.string} 登录成功")
            
            // 更新玩家游戏名（以防玩家改名）并获取用户详情
            val playerData = PlayerDataManager.getPlayerData(uuid)
            if (playerData != null) {
                PlayerDataManager.updatePlayerName(uuid, player.name.string)
                fetchAndSetPlayerPrefix(player, playerData.apiUid)
                // 播报欢迎词
                WelcomeManager.broadcastWelcome((player.getEntityWorld() as net.minecraft.server.world.ServerWorld).server, playerData.apiUid, player.name.string)
            }
        } else {
            // 检查是否是系统错误（API 不可用）
            val isSystemError = result.errorCode == "system_error"
            if (isSystemError) {
                LoginManager.setApiAvailable(false)
                player.sendMessage(Text.literal("§cAPI 连接失败！").formatted(Formatting.RED))
                if (PlayerDataManager.hasBackupPassword(uuid)) {
                    player.sendMessage(Text.literal("§e您可以使用 §f/dl <备用密码> §e进行备用登录。").formatted(Formatting.YELLOW))
                } else {
                    player.sendMessage(Text.literal("§e您尚未设置备用密码，请等待 API 恢复后重试。").formatted(Formatting.YELLOW))
                }
                return
            }
            
            // API 响应正常，标记 API 可用
            LoginManager.setApiAvailable(true)
            
            // 处理密码错误（仅当错误码是密码错误时）
            val isPasswordError = result.errorCode == "error_password"
            if (isPasswordError) {
                val wrongResult = LoginManager.recordWrongPassword(uuid)
                when (wrongResult) {
                    LoginManager.WrongPasswordResult.KICK -> {
                        player.networkHandler.disconnect(
                            Text.literal("§c密码错误次数过多，您已被封禁 ${Config.wrongPasswordKickHours} 小时。")
                        )
                        return
                    }
                    LoginManager.WrongPasswordResult.COOLDOWN -> {
                        player.sendMessage(Text.literal("§c密码错误次数过多，请等待 ${Config.wrongPasswordCooldownSeconds} 秒后再试。").formatted(Formatting.RED))
                        val remaining = LoginManager.getRemainingWrongAttempts(uuid)
                        player.sendMessage(Text.literal("§e剩余尝试次数: $remaining").formatted(Formatting.YELLOW))
                        return
                    }
                    LoginManager.WrongPasswordResult.NORMAL -> {
                        // 继续正常流程
                    }
                }
            }
            
            val errorMsg = ApiService.getErrorMessage(result.errorCode ?: "system_error")
            player.sendMessage(Text.literal("§c登录失败: $errorMsg").formatted(Formatting.RED))
            
            val remaining = LoginManager.getRemainingWrongAttempts(uuid)
            if (remaining > 0) {
                player.sendMessage(Text.literal("§e剩余尝试次数: $remaining").formatted(Formatting.YELLOW))
            }
        }
    }
    
    /**
     * 刷新玩家背包
     * @param player 玩家实体
     */
    private fun refreshPlayerInventory(player: ServerPlayerEntity) {
        // 同步玩家背包状态到客户端
        player.playerScreenHandler.syncState()
    }
    
    /**
     * 获取用户详情并设置玩家名称前缀
     * @param player 玩家实体
     * @param apiUid API 账号 UID
     */
    private fun fetchAndSetPlayerPrefix(player: ServerPlayerEntity, apiUid: Long) {
        ApiService.getUserDetailAsync(apiUid).thenAccept { result ->
            (player.getEntityWorld() as net.minecraft.server.world.ServerWorld).server.execute {
                if (!player.isRemoved && result.success) {
                    val apiUsername = result.username
                    val experience = result.experience ?: 0
                    if (!apiUsername.isNullOrBlank()) {
                        // 更新存储的 API 用户名
                        PlayerDataManager.updateApiUsername(player.uuid, apiUsername)
                        
                        // 根据经验值计算等级并设置带颜色的前缀
                        val level = getLevelFromExperience(experience)
                        setPlayerTeamPrefix(player, apiUsername, level)
                        
                        Ohc_login.logger.info("玩家 ${player.name.string} 的显示名称已设置为: [$apiUsername] (等级: $level, 经验: $experience)")
                    }
                } else if (!result.success) {
                    Ohc_login.logger.warn("获取玩家 ${player.name.string} 的 API 用户详情失败: ${result.errorCode}")
                }
            }
        }
    }
    
    /**
     * 根据经验值计算等级
     * 零级:ZERO——EXP:0 ~ 49
     * 一级:UNO——EXP:50 ~ 499
     * 二级:DUE——EXP:500 ~ 999
     * 三级:TRE——EXP:1000 ~ 2999
     * 四级:QUATTRO——EXP:3000 ~ 7999
     * 五级:CINQUE——EXP:8000 ~ 14999
     * 六级:SEI——EXP:15000 ~ 29999
     * 七级:SETTE——EXP:30000 ~ 79999
     * 八级:OTTO——EXP:80000 ~ ∞
     */
    private fun getLevelFromExperience(experience: Int): Int {
        return when {
            experience >= 80000 -> 8
            experience >= 30000 -> 7
            experience >= 15000 -> 6
            experience >= 8000 -> 5
            experience >= 3000 -> 4
            experience >= 1000 -> 3
            experience >= 500 -> 2
            experience >= 50 -> 1
            else -> 0
        }
    }
    
    /**
     * 根据等级获取带颜色的前缀文本
     * 0级: 白色
     * 1-7级: 红、橙、黄、绿、青、蓝、紫
     * 8级: 渐变色
     */
    private fun getColoredPrefix(apiUsername: String, level: Int): Text {
        return when (level) {
            0 -> Text.literal("§f[$apiUsername] §r") // 白色
            1 -> Text.literal("§c[$apiUsername] §r") // 红色
            2 -> Text.literal("§6[$apiUsername] §r") // 橙色
            3 -> Text.literal("§e[$apiUsername] §r") // 黄色
            4 -> Text.literal("§a[$apiUsername] §r") // 绿色
            5 -> Text.literal("§b[$apiUsername] §r") // 青色
            6 -> Text.literal("§9[$apiUsername] §r") // 蓝色
            7 -> Text.literal("§d[$apiUsername] §r") // 紫色
            8 -> {
                // 炫彩色：每个字符使用不同颜色
                val colors = listOf("§c", "§6", "§e", "§a", "§b", "§9", "§d")
                val coloredName = StringBuilder("[")
                apiUsername.forEachIndexed { index, char ->
                    coloredName.append(colors[index % colors.size]).append(char)
                }
                coloredName.append("§f] §r")
                Text.literal(coloredName.toString())
            }
            else -> Text.literal("§f[$apiUsername] §r") // 默认白色
        }
    }
    
    /**
     * 使用 Scoreboard Team 设置玩家名称前缀
     * @param player 玩家实体
     * @param apiUsername API 用户名
     * @param level 玩家等级
     */
    private fun setPlayerTeamPrefix(player: ServerPlayerEntity, apiUsername: String, level: Int) {
        val server = (player.getEntityWorld() as net.minecraft.server.world.ServerWorld).server
        val scoreboard = server.scoreboard
        val playerName = player.gameProfile.name
        
        // 创建或获取玩家专属的 Team（使用玩家名作为 Team 名，避免冲突）
        val teamName = "ohc_${playerName.take(12)}" // Team 名称最长 16 字符
        var team = scoreboard.getTeam(teamName)
        
        if (team == null) {
            team = scoreboard.addTeam(teamName)
        }
        
        // 根据等级设置带颜色的前缀
        team.prefix = getColoredPrefix(apiUsername, level)
        
        // 将玩家加入 Team
        scoreboard.addScoreHolderToTeam(playerName, team)
    }
    
    /**
     * 执行解绑自己的命令（需要密码验证）
     */
    private fun executeUnbindSelf(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val player = source.player ?: run {
            source.sendError(Text.literal("此命令只能由玩家执行"))
            return 0
        }
        
        val uuid = player.uuid
        val playerData = PlayerDataManager.getPlayerData(uuid)
        
        if (playerData == null) {
            player.sendMessage(Text.literal("§c您还没有绑定账号。").formatted(Formatting.RED))
            return 0
        }
        
        val password = StringArgumentType.getString(context, "password")
        
        player.sendMessage(Text.literal("§e正在验证密码...").formatted(Formatting.YELLOW))
        
        // 使用绑定的 UID 验证密码
        val account = playerData.apiUid.toString()
        
        // 异步调用 API 验证密码
        ApiService.loginAsync(account, password).thenAccept { result ->
            (player.getEntityWorld() as net.minecraft.server.world.ServerWorld).server.execute {
                if (!player.isRemoved) {
                    if (result.success) {
                        // 密码验证成功，执行解绑
                        if (PlayerDataManager.unbindPlayer(uuid)) {
                            player.sendMessage(Text.literal("§a已解绑您的账号。下次登录需要重新绑定。").formatted(Formatting.GREEN))
                            Ohc_login.logger.info("玩家 ${player.name.string} 已解绑账号")
                            // 如果玩家在线且已登录，需要重新登录
                            if (LoginManager.isLoggedIn(uuid)) {
                                LoginManager.onPlayerJoin(player)
                            }
                        }
                    } else {
                        val errorMsg = ApiService.getErrorMessage(result.errorCode ?: "system_error")
                        player.sendMessage(Text.literal("§c解绑失败: $errorMsg").formatted(Formatting.RED))
                    }
                }
            }
        }
        
        return 1
    }
    
    /**
     * 执行解绑指定玩家的命令（需要 OP 权限）
     */
    private fun executeUnbindPlayer(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val playerName = StringArgumentType.getString(context, "playerName")
        
        // 查找玩家 UUID（优先在线玩家，其次使用服务器用户缓存）
        val server = source.server
        val targetPlayer = server.playerManager.getPlayer(playerName)
        val targetUuid = targetPlayer?.uuid 
            ?: PlayerDataManager.findUuidByName(playerName)
        
        if (targetUuid == null) {
            source.sendError(Text.literal("§c找不到玩家: $playerName"))
            return 0
        }
        
        if (PlayerDataManager.unbindPlayer(targetUuid)) {
            source.sendFeedback({ Text.literal("§a已解绑玩家 $playerName 的账号。") }, true)
            Ohc_login.logger.info("管理员 ${source.name} 解绑了玩家 $playerName 的账号")
            
            // 如果目标玩家在线且已登录，需要重新登录
            if (targetPlayer != null && LoginManager.isLoggedIn(targetUuid)) {
                targetPlayer.sendMessage(Text.literal("§c您的账号已被管理员解绑，请重新绑定。").formatted(Formatting.RED))
                LoginManager.onPlayerJoin(targetPlayer)
            }
        } else {
            source.sendError(Text.literal("§c玩家 $playerName 还没有绑定账号。"))
        }
        
        return 1
    }
    
    /**
     * 执行管理员让玩家登录命令
     */
    private fun executeOhlogin(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val playerName = StringArgumentType.getString(context, "playerName")
        val server = source.server
        
        // 查找在线玩家
        val targetPlayer = server.playerManager.getPlayer(playerName)
        if (targetPlayer == null) {
            source.sendError(Text.literal("§c玩家 $playerName 不在线"))
            return 0
        }
        
        val uuid = targetPlayer.uuid
        
        // 检查是否已登录
        if (LoginManager.isLoggedIn(uuid)) {
            source.sendError(Text.literal("§c玩家 $playerName 已经登录了"))
            return 0
        }
        
        // 检查是否需要绑定
        if (LoginManager.needsBind(uuid)) {
            source.sendError(Text.literal("§c玩家 $playerName 还没有绑定账号，无法直接登录"))
            return 0
        }
        
        // 直接完成登录
        LoginManager.completeLogin(uuid)
        LoginManager.clearWrongPasswordRecord(uuid)
        
        // 刷新玩家背包
        refreshPlayerInventory(targetPlayer)
        
        targetPlayer.sendMessage(Text.literal("§a管理员已帮您登录！").formatted(Formatting.GREEN))
        source.sendFeedback({ Text.literal("§a已让玩家 $playerName 登录") }, true)
        Ohc_login.logger.info("管理员 ${source.name} 让玩家 $playerName 登录")
        
        // 更新游戏名并设置前缀
        val playerData = PlayerDataManager.getPlayerData(uuid)
        if (playerData != null) {
            PlayerDataManager.updatePlayerName(uuid, targetPlayer.name.string)
            fetchAndSetPlayerPrefix(targetPlayer, playerData.apiUid)
            // 播报欢迎词
            server.let { WelcomeManager.broadcastWelcome(it, playerData.apiUid, targetPlayer.name.string) }
        }
        
        return 1
    }
    
    /**
     * 执行查看封禁列表命令
     */
    private fun executeOhbanList(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val server = source.server
        val bannedPlayers = LoginManager.getBannedPlayers()
        val bannedUids = LoginManager.getBannedUids()
        
        if (bannedPlayers.isEmpty() && bannedUids.isEmpty()) {
            source.sendFeedback({ Text.literal("§a当前没有封禁记录。") }, false)
            return 1
        }
        
        // 显示被封禁的 UID
        if (bannedUids.isNotEmpty()) {
            source.sendFeedback({ Text.literal("§6=== UID 封禁列表 ===") }, false)
            for ((uid, info) in bannedUids) {
                val (remainingHours, reason) = info
                val timeStr = if (remainingHours != null) "剩余 §c${String.format("%.1f", remainingHours)} §7小时" else "§c永久"
                val reasonStr = if (!reason.isNullOrBlank()) " §7| §e$reason" else ""
                source.sendFeedback({ Text.literal("§eUID: $uid §7- $timeStr$reasonStr") }, false)
            }
            source.sendFeedback({ Text.literal("§6共 ${bannedUids.size} 个 UID 被封禁") }, false)
        }
        
        // 显示被封禁的玩家（密码错误封禁）
        if (bannedPlayers.isNotEmpty()) {
            source.sendFeedback({ Text.literal("§6=== 密码错误封禁列表 ===") }, false)
            for ((uuid, remainingHours) in bannedPlayers) {
                val playerName = server.playerManager.getPlayer(uuid)?.name?.string
                    ?: PlayerDataManager.findNameByUuid(uuid)
                    ?: uuid.toString()
                source.sendFeedback({ 
                    Text.literal("§e$playerName §7- 剩余 §c${String.format("%.1f", remainingHours)} §7小时") 
                }, false)
            }
            source.sendFeedback({ Text.literal("§6共 ${bannedPlayers.size} 名玩家被封禁") }, false)
        }
        
        return 1
    }
    
    /**
     * 执行按 UID 封禁命令
     * @param reason 封禁原因（可选）
     * @param hours 封禁时长（可选）
     */
    private fun executeOhbanByUid(context: CommandContext<ServerCommandSource>, reason: String?, hours: Double?): Int {
        val source = context.source
        val uidStr = StringArgumentType.getString(context, "uid")
        
        val uid = uidStr.toLongOrNull()
        if (uid == null) {
            source.sendError(Text.literal("§cUID 必须是数字"))
            return 0
        }
        
        // 封禁 UID
        LoginManager.banUid(uid, hours, reason)
        
        val server = source.server
        val playerUuids = PlayerDataManager.getPlayersByApiUid(uid)
        var kickedCount = 0
        
        // 踢出已绑定该 UID 的在线玩家
        for (uuid in playerUuids) {
            val onlinePlayer = server.playerManager.getPlayer(uuid)
            if (onlinePlayer != null) {
                val kickMsg = buildString {
                    append("§c您的账号(UID: $uid)已被封禁")
                    if (hours != null) append("，时长: ${String.format("%.1f", hours)} 小时")
                    else append("（永久）")
                    if (!reason.isNullOrBlank()) append("\n§e原因: $reason")
                }
                onlinePlayer.networkHandler.disconnect(Text.literal(kickMsg))
                kickedCount++
            }
        }
        
        // 构建反馈消息
        val feedbackMsg = buildString {
            append("§a已封禁 UID $uid")
            if (hours != null) append("，时长: ${String.format("%.1f", hours)} 小时")
            else append("（永久）")
            if (!reason.isNullOrBlank()) append("\n§e原因: $reason")
            if (playerUuids.isNotEmpty()) {
                val playerNames = playerUuids.mapNotNull { uuid ->
                    PlayerDataManager.findNameByUuid(uuid)
                }.joinToString(", ")
                append("\n§7关联玩家: $playerNames")
                if (kickedCount > 0) append(" (已踢出 $kickedCount 人)")
            }
        }
        
        source.sendFeedback({ Text.literal(feedbackMsg) }, true)
        Ohc_login.logger.info("管理员 ${source.name} 封禁了 UID $uid" + 
            (if (hours != null) "，时长: $hours 小时" else "（永久）") +
            (if (!reason.isNullOrBlank()) "，原因: $reason" else ""))
        
        return 1
    }
    
    /**
     * 执行解除封禁命令（支持 UID 或玩家名）
     */
    private fun executeOhunban(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val target = StringArgumentType.getString(context, "target")
        val server = source.server
        
        // 尝试解析为 UID
        val uid = target.toLongOrNull()
        if (uid != null) {
            if (LoginManager.unbanUid(uid)) {
                source.sendFeedback({ Text.literal("§a已解除 UID $uid 的封禁。") }, true)
                Ohc_login.logger.info("管理员 ${source.name} 解除了 UID $uid 的封禁")
                return 1
            } else {
                source.sendError(Text.literal("§cUID $uid 未被封禁。"))
                return 0
            }
        }
        
        // 作为玩家名处理
        val targetPlayer = server.playerManager.getPlayer(target)
        val targetUuid = targetPlayer?.uuid ?: PlayerDataManager.findUuidByName(target)
        
        if (targetUuid == null) {
            source.sendError(Text.literal("§c找不到玩家: $target"))
            return 0
        }
        
        if (LoginManager.unbanPlayer(targetUuid)) {
            source.sendFeedback({ Text.literal("§a已解除玩家 $target 的封禁。") }, true)
            Ohc_login.logger.info("管理员 ${source.name} 解除了玩家 $target 的密码错误封禁")
        } else {
            source.sendError(Text.literal("§c玩家 $target 未被封禁。"))
        }
        
        return 1
    }
    
    /**
     * 查看欢迎词列表
     */
    private fun executeOhwelList(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val welcomes = WelcomeManager.getAllWelcomes()
        
        if (welcomes.isEmpty()) {
            source.sendFeedback({ Text.literal("§a当前没有设置欢迎词。") }, false)
            return 1
        }
        
        source.sendFeedback({ Text.literal("§6=== 欢迎词列表 ===") }, false)
        
        for ((uid, msg) in welcomes) {
            source.sendFeedback({ Text.literal("§eUID: $uid §7-> §f$msg") }, false)
        }
        
        source.sendFeedback({ Text.literal("§6共 ${welcomes.size} 条欢迎词") }, false)
        return 1
    }
    
    /**
     * 设置欢迎词
     */
    private fun executeOhwelSet(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val uidStr = StringArgumentType.getString(context, "uid")
        val message = StringArgumentType.getString(context, "message")
        
        val uid = uidStr.toLongOrNull()
        if (uid == null) {
            source.sendError(Text.literal("§cUID 必须是数字"))
            return 0
        }
        
        WelcomeManager.setWelcome(uid, message)
        source.sendFeedback({ Text.literal("§a已设置 UID $uid 的欢迎词: $message") }, true)
        source.sendFeedback({ Text.literal("§7提示: 可用 {player} 作为玩家名占位符") }, false)
        Ohc_login.logger.info("管理员 ${source.name} 设置了 UID $uid 的欢迎词")
        return 1
    }
    
    /**
     * 删除欢迎词
     */
    private fun executeOhwelDel(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val uidStr = StringArgumentType.getString(context, "uid")
        
        val uid = uidStr.toLongOrNull()
        if (uid == null) {
            source.sendError(Text.literal("§cUID 必须是数字"))
            return 0
        }
        
        if (WelcomeManager.removeWelcome(uid)) {
            source.sendFeedback({ Text.literal("§a已删除 UID $uid 的欢迎词") }, true)
            Ohc_login.logger.info("管理员 ${source.name} 删除了 UID $uid 的欢迎词")
        } else {
            source.sendError(Text.literal("§cUID $uid 没有设置欢迎词"))
        }
        return 1
    }
    
    /**
     * 查询绑定信息
     * 输入UID则查该UID绑定的所有玩家
     * 输入玩家名则查该玩家绑定的UID及同UID的其他玩家
     */
    private fun executeOhbind(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val server = source.server
        val query = StringArgumentType.getString(context, "query")
        
        // 尝试解析为UID
        val uid = query.toLongOrNull()
        
        if (uid != null) {
            // 按UID查询
            val players = PlayerDataManager.getPlayersByApiUid(uid)
            if (players.isEmpty()) {
                source.sendFeedback({ Text.literal("§eUID $uid 没有绑定任何玩家") }, false)
                return 1
            }
            
            source.sendFeedback({ Text.literal("§6=== UID $uid 绑定的玩家 ===") }, false)
            for (playerUuid in players) {
                val name = server.playerManager.getPlayer(playerUuid)?.name?.string
                    ?: PlayerDataManager.findNameByUuid(playerUuid)
                    ?: playerUuid.toString()
                val data = PlayerDataManager.getPlayerData(playerUuid)
                val apiName = data?.apiUsername ?: "未知"
                source.sendFeedback({ Text.literal("§e- $name §7(API名: $apiName)") }, false)
            }
            source.sendFeedback({ Text.literal("§6共 ${players.size}/${Config.maxBindPerUid} 个玩家") }, false)
        } else {
            // 按玩家名查询
            val data = PlayerDataManager.getPlayerDataByName(server, query)
            if (data == null) {
                source.sendError(Text.literal("§c找不到玩家 $query 的绑定信息"))
                return 0
            }
            
            val boundUid = data.apiUid
            val apiName = data.apiUsername ?: "未知"
            source.sendFeedback({ Text.literal("§6=== 玩家 $query 的绑定信息 ===") }, false)
            source.sendFeedback({ Text.literal("§e绑定UID: $boundUid §7(API名: $apiName)") }, false)
            
            // 查找同UID的其他玩家
            val samePlayers = PlayerDataManager.getPlayersByApiUid(boundUid)
            if (samePlayers.size > 1) {
                source.sendFeedback({ Text.literal("§6同UID绑定的其他玩家:") }, false)
                for (playerUuid in samePlayers) {
                    val pData = PlayerDataManager.getPlayerData(playerUuid) ?: continue
                    if (pData.uuid == data.uuid) continue
                    val name = server.playerManager.getPlayer(playerUuid)?.name?.string
                        ?: PlayerDataManager.findNameByUuid(playerUuid)
                        ?: playerUuid.toString()
                    source.sendFeedback({ Text.literal("§e- $name") }, false)
                }
            }
            source.sendFeedback({ Text.literal("§6该UID共绑定 ${samePlayers.size}/${Config.maxBindPerUid} 个玩家") }, false)
        }
        
        return 1
    }
    
    /**
     * 计算密码的 SHA-256 哈希
     */
    private fun hashPassword(password: String): String {
        val digest = MessageDigest.getInstance("SHA-256")
        val hashBytes = digest.digest(password.toByteArray(Charsets.UTF_8))
        return hashBytes.joinToString("") { "%02x".format(it) }
    }
    
    /**
     * 执行创建备用密码命令 /r <密码>
     * 已绑定玩家：登录后设置备用密码
     * 未绑定玩家：创建临时账号
     */
    private fun executeRegisterBackup(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val player = source.player ?: run {
            source.sendError(Text.literal("此命令只能由玩家执行"))
            return 0
        }
        
        // 检查是否启用备用登录
        if (!Config.enableBackupLogin) {
            player.sendMessage(Text.literal("§c备用登录功能已禁用。").formatted(Formatting.RED))
            return 0
        }
        
        // API 正常时禁止使用 /r
        if (LoginManager.isApiAvailable()) {
            player.sendMessage(Text.literal("§cAPI 正常，无需创建备用密码。").formatted(Formatting.RED))
            return 0
        }
        
        val uuid = player.uuid
        val isBound = PlayerDataManager.isBound(uuid)
        
        val password = StringArgumentType.getString(context, "password")
        
        // 密码长度检查
        if (password.length < 4) {
            player.sendMessage(Text.literal("§c密码长度至少为4位！").formatted(Formatting.RED))
            return 0
        }
        
        val passwordHash = hashPassword(password)
        
        if (isBound) {
            // 已绑定玩家
            // 检查是否已有备用密码
            if (PlayerDataManager.hasBackupPassword(uuid)) {
                player.sendMessage(Text.literal("§c您已设置过备用密码，请使用 /up <当前密码> <新密码> 修改。").formatted(Formatting.RED))
                return 0
            }
            
            // 创建备用密码并直接登录
            if (PlayerDataManager.setBackupPassword(uuid, passwordHash)) {
                LoginManager.completeBackupLogin(uuid)
                refreshPlayerInventory(player)
                
                player.sendMessage(Text.literal("§a备用密码设置成功，已自动登录！").formatted(Formatting.GREEN))
                Ohc_login.logger.info("玩家 ${player.name.string} 设置了备用密码并自动登录")
                
                // 设置前缀
                val playerData = PlayerDataManager.getPlayerData(uuid)
                if (playerData != null) {
                    fetchAndSetPlayerPrefix(player, playerData.apiUid)
                }
            } else {
                player.sendMessage(Text.literal("§c设置备用密码失败，请稍后重试。").formatted(Formatting.RED))
            }
        } else {
            // 未绑定玩家：创建临时账号
            // 检查是否已有临时账号
            if (PlayerDataManager.hasTempAccount(uuid)) {
                player.sendMessage(Text.literal("§c您已创建过临时账号，请使用 /up <当前密码> <新密码> 修改密码。").formatted(Formatting.RED))
                return 0
            }
            
            if (PlayerDataManager.createTempAccount(uuid, passwordHash)) {
                // 创建成功后直接登录（标记为备用登录）
                LoginManager.completeBackupLogin(uuid)
                refreshPlayerInventory(player)
                
                player.sendMessage(Text.literal("§a临时账号创建成功，已自动登录！").formatted(Formatting.GREEN))
                player.sendMessage(Text.literal("§eAPI恢复后请使用 §f/bind §e绑定正式账号。").formatted(Formatting.YELLOW))
                Ohc_login.logger.info("玩家 ${player.name.string} 创建了临时账号并自动登录")
            } else {
                player.sendMessage(Text.literal("§c创建临时账号失败，请稍后重试。").formatted(Formatting.RED))
            }
        }
        
        return 1
    }
    
    /**
     * 执行备用登录命令 /dl <密码>
     * 支持已绑定玩家的备用密码和未绑定玩家的临时账号
     */
    private fun executeBackupLogin(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val player = source.player ?: run {
            source.sendError(Text.literal("此命令只能由玩家执行"))
            return 0
        }
        
        // 检查是否启用备用登录
        if (!Config.enableBackupLogin) {
            player.sendMessage(Text.literal("§c备用登录功能已禁用。").formatted(Formatting.RED))
            return 0
        }
        
        val uuid = player.uuid
        
        // 检查是否已登录
        if (LoginManager.isLoggedIn(uuid)) {
            player.sendMessage(Text.literal("§c您已经登录了！").formatted(Formatting.RED))
            return 0
        }
        
        val isBound = PlayerDataManager.isBound(uuid)
        val hasTempAccount = PlayerDataManager.hasTempAccount(uuid)
        val hasBackupPassword = PlayerDataManager.hasBackupPassword(uuid)
        
        // 检查是否有可用的备用登录方式
        if (!hasBackupPassword && !hasTempAccount) {
            player.sendMessage(Text.literal("§c您还没有设置备用密码，请使用 /r <密码> 创建。").formatted(Formatting.RED))
            return 0
        }
        
        // 检查 API 是否可用（只有 API 不可用时才允许备用登录）
        if (LoginManager.isApiAvailable()) {
            if (isBound) {
                player.sendMessage(Text.literal("§cAPI 正常，请使用 /l <密码> 登录。").formatted(Formatting.RED))
            } else {
                player.sendMessage(Text.literal("§cAPI 正常，请使用 /bind <账号> <密码> 绑定账号。").formatted(Formatting.RED))
            }
            return 0
        }
        
        // 检查 UID 是否被封禁（已绑定玩家）
        if (isBound) {
            val playerData = PlayerDataManager.getPlayerData(uuid)
            if (playerData != null) {
                val uidBanInfo = LoginManager.getUidBanInfo(playerData.apiUid)
                if (uidBanInfo != null) {
                    val (remainingHours, reason) = uidBanInfo
                    val banMsg = buildString {
                        append("§c您的账号(UID: ${playerData.apiUid})已被封禁")
                        if (remainingHours != null) append("，剩余: ${String.format("%.1f", remainingHours)} 小时")
                        else append("（永久）")
                        if (!reason.isNullOrBlank()) append("\n§e原因: $reason")
                    }
                    player.sendMessage(Text.literal(banMsg).formatted(Formatting.RED))
                    return 0
                }
            }
        }
        
        // 检查是否被封禁（密码错误封禁）
        val banHours = LoginManager.getBanRemainingHours(uuid)
        if (banHours != null) {
            player.sendMessage(Text.literal("§c您已被封禁，剩余时间: ${String.format("%.1f", banHours)} 小时").formatted(Formatting.RED))
            return 0
        }
        
        // 检查是否在冷却中
        val cooldownSeconds = LoginManager.getCooldownRemainingSeconds(uuid)
        if (cooldownSeconds != null) {
            player.sendMessage(Text.literal("§c请等待 $cooldownSeconds 秒后再试。").formatted(Formatting.RED))
            return 0
        }
        
        val password = StringArgumentType.getString(context, "password")
        val passwordHash = hashPassword(password)
        
        // 验证密码（优先检查正式备用密码，其次临时账号）
        val passwordValid = if (hasBackupPassword) {
            PlayerDataManager.verifyBackupPassword(uuid, passwordHash)
        } else {
            PlayerDataManager.verifyTempPassword(uuid, passwordHash)
        }
        
        if (passwordValid) {
            LoginManager.completeBackupLogin(uuid)
            LoginManager.clearWrongPasswordRecord(uuid)
            refreshPlayerInventory(player)
            
            if (isBound) {
                player.sendMessage(Text.literal("§a备用登录成功！欢迎回来，${player.name.string}！").formatted(Formatting.GREEN))
                // 设置前缀
                val playerData = PlayerDataManager.getPlayerData(uuid)
                if (playerData != null) {
                    fetchAndSetPlayerPrefix(player, playerData.apiUid)
                }
            } else {
                player.sendMessage(Text.literal("§a临时账号登录成功！欢迎，${player.name.string}！").formatted(Formatting.GREEN))
                player.sendMessage(Text.literal("§e您正在使用临时账号，API恢复后请使用 §f/bind §e绑定正式账号。").formatted(Formatting.YELLOW))
            }
            Ohc_login.logger.info("玩家 ${player.name.string} 使用${if (isBound) "备用密码" else "临时账号"}登录成功")
        } else {
            // 记录密码错误
            val wrongResult = LoginManager.recordWrongPassword(uuid)
            when (wrongResult) {
                LoginManager.WrongPasswordResult.KICK -> {
                    player.networkHandler.disconnect(
                        Text.literal("§c密码错误次数过多，您已被封禁 ${Config.wrongPasswordKickHours} 小时。")
                    )
                    return 0
                }
                LoginManager.WrongPasswordResult.COOLDOWN -> {
                    player.sendMessage(Text.literal("§c密码错误次数过多，请等待 ${Config.wrongPasswordCooldownSeconds} 秒后再试。").formatted(Formatting.RED))
                }
                LoginManager.WrongPasswordResult.NORMAL -> {
                    player.sendMessage(Text.literal("§c密码错误！").formatted(Formatting.RED))
                }
            }
            val remaining = LoginManager.getRemainingWrongAttempts(uuid)
            if (remaining > 0) {
                player.sendMessage(Text.literal("§e剩余尝试次数: $remaining").formatted(Formatting.YELLOW))
            }
        }
        
        return 1
    }
    
    /**
     * 执行修改备用密码命令 /up <当前密码> <新密码>
     */
    private fun executeUpdateBackupPassword(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val player = source.player ?: run {
            source.sendError(Text.literal("此命令只能由玩家执行"))
            return 0
        }
        
        // 检查是否启用备用登录
        if (!Config.enableBackupLogin) {
            player.sendMessage(Text.literal("§c备用登录功能已禁用。").formatted(Formatting.RED))
            return 0
        }
        
        val uuid = player.uuid
        val isBound = PlayerDataManager.isBound(uuid)
        val hasTempAccount = PlayerDataManager.hasTempAccount(uuid)
        val hasBackupPassword = PlayerDataManager.hasBackupPassword(uuid)
        
        // 必须已登录
        if (!LoginManager.isLoggedIn(uuid)) {
            player.sendMessage(Text.literal("§c请先登录后再修改密码！").formatted(Formatting.RED))
            return 0
        }
        
        // 检查是否有可修改的密码
        if (!hasBackupPassword && !hasTempAccount) {
            player.sendMessage(Text.literal("§c您还没有设置备用密码，请使用 /r <密码> 设置。").formatted(Formatting.RED))
            return 0
        }
        
        val currentPassword = StringArgumentType.getString(context, "currentPassword")
        val newPassword = StringArgumentType.getString(context, "newPassword")
        val currentHash = hashPassword(currentPassword)
        
        // 验证当前密码
        val passwordValid = if (hasBackupPassword) {
            PlayerDataManager.verifyBackupPassword(uuid, currentHash)
        } else {
            PlayerDataManager.verifyTempPassword(uuid, currentHash)
        }
        
        if (!passwordValid) {
            player.sendMessage(Text.literal("§c当前密码错误！").formatted(Formatting.RED))
            return 0
        }
        
        // 新密码长度检查
        if (newPassword.length < 4) {
            player.sendMessage(Text.literal("§c新密码长度至少为4位！").formatted(Formatting.RED))
            return 0
        }
        
        val newHash = hashPassword(newPassword)
        val success = if (hasBackupPassword) {
            PlayerDataManager.setBackupPassword(uuid, newHash)
        } else {
            PlayerDataManager.updateTempPassword(uuid, newHash)
        }
        
        if (success) {
            player.sendMessage(Text.literal("§a密码修改成功！").formatted(Formatting.GREEN))
            Ohc_login.logger.info("玩家 ${player.name.string} 修改了${if (isBound) "备用" else "临时账号"}密码")
        } else {
            player.sendMessage(Text.literal("§c修改密码失败，请稍后重试。").formatted(Formatting.RED))
        }
        
        return 1
    }
    
    /**
     * /where 命令模式
     */
    private enum class WhereMode {
        NORMAL,    // 普通查询
        BROADCAST, // 全服广播
        SEE,       // 实时追踪
        STOP       // 停止追踪
    }
    
    /**
     * 执行查询玩家位置命令 /where <玩家> [all|see|stop]
     */
    private fun executeWhere(context: CommandContext<ServerCommandSource>, mode: WhereMode): Int {
        val source = context.source
        val playerName = StringArgumentType.getString(context, "playerName")
        val server = source.server
        val executor = source.player
        
        // stop 模式不需要目标玩家在线
        if (mode == WhereMode.STOP) {
            if (executor == null) {
                source.sendError(Text.literal("§c此命令只能由玩家执行"))
                return 0
            }
            if (trackingPlayers.remove(executor.uuid) != null) {
                source.sendFeedback({ Text.literal("§a已停止追踪玩家 $playerName") }, false)
            } else {
                source.sendFeedback({ Text.literal("§e您没有在追踪任何玩家") }, false)
            }
            return 1
        }
        
        val targetPlayer = server.playerManager.getPlayer(playerName)
        if (targetPlayer == null) {
            source.sendError(Text.literal("§c玩家 $playerName 不在线"))
            return 0
        }
        
        when (mode) {
            WhereMode.SEE -> {
                if (executor == null) {
                    source.sendError(Text.literal("§c此命令只能由玩家执行"))
                    return 0
                }
                trackingPlayers[executor.uuid] = playerName
                source.sendFeedback({ Text.literal("§a已开始追踪玩家 $playerName，使用 /where $playerName stop 停止") }, false)
            }
            WhereMode.BROADCAST -> {
                val pos = targetPlayer.blockPos
                val world = targetPlayer.entityWorld.registryKey.value.toString()
                val msg = Text.literal("§6玩家 §e$playerName §6位于 §f$world §7(§f${pos.x}, ${pos.y}, ${pos.z}§7)")
                server.playerManager.broadcast(msg, false)
            }
            else -> {
                val pos = targetPlayer.blockPos
                val world = targetPlayer.entityWorld.registryKey.value.toString()
                val msg = Text.literal("§6玩家 §e$playerName §6位于 §f$world §7(§f${pos.x}, ${pos.y}, ${pos.z}§7)")
                source.sendFeedback({ msg }, false)
            }
        }
        
        return 1
    }
    
    /**
     * 更新追踪显示（每 tick 调用）
     */
    fun updateTracking(server: net.minecraft.server.MinecraftServer) {
        val iterator = trackingPlayers.entries.iterator()
        while (iterator.hasNext()) {
            val (observerUuid, targetName) = iterator.next()
            val observer = server.playerManager.getPlayer(observerUuid)
            val target = server.playerManager.getPlayer(targetName)
            
            // 观察者离线则移除
            if (observer == null) {
                iterator.remove()
                continue
            }
            
            // 目标离线则提示并移除
            if (target == null) {
                observer.sendMessage(Text.literal("§e玩家 $targetName 已离线，追踪已停止"), true)
                iterator.remove()
                continue
            }
            
            val pos = target.blockPos
            val world = target.entityWorld.registryKey.value.path  // 只取路径部分，更简洁
            observer.sendMessage(
                Text.literal("§e$targetName §7| §f$world §7(§f${pos.x}, ${pos.y}, ${pos.z}§7)"),
                true  // ActionBar
            )
        }
    }
    
    /**
     * 执行管理员修改玩家备用密码命令 /dup <玩家> [密码]
     */
    private fun executeAdminSetBackupPassword(context: CommandContext<ServerCommandSource>, password: String?): Int {
        val source = context.source
        val playerName = StringArgumentType.getString(context, "playerName")
        val server = source.server
        
        // 查找玩家 UUID
        val targetPlayer = server.playerManager.getPlayer(playerName)
        val targetUuid = targetPlayer?.uuid 
            ?: PlayerDataManager.findUuidByName(playerName)
        
        if (targetUuid == null) {
            source.sendError(Text.literal("§c找不到玩家: $playerName"))
            return 0
        }
        
        val isBound = PlayerDataManager.isBound(targetUuid)
        val hasTempAccount = PlayerDataManager.hasTempAccount(targetUuid)
        val hasBackupPassword = PlayerDataManager.hasBackupPassword(targetUuid)
        
        if (password == null) {
            // 删除密码
            val deleted = if (hasBackupPassword) {
                PlayerDataManager.removeBackupPassword(targetUuid)
            } else if (hasTempAccount) {
                PlayerDataManager.removeTempAccount(targetUuid)
            } else {
                false
            }
            
            if (deleted) {
                val type = if (hasBackupPassword) "备用密码" else "临时账号"
                source.sendFeedback({ Text.literal("§a已删除玩家 $playerName 的$type") }, true)
                Ohc_login.logger.info("管理员 ${source.name} 删除了玩家 $playerName 的$type")
                targetPlayer?.sendMessage(Text.literal("§e您的${type}已被管理员删除。").formatted(Formatting.YELLOW))
                
                // 如果玩家在线且通过备用登录，强制重新登录
                if (targetPlayer != null && LoginManager.isBackupLogged(targetUuid)) {
                    targetPlayer.sendMessage(Text.literal("§c您需要重新登录。").formatted(Formatting.RED))
                    LoginManager.forceRelogin(targetPlayer)
                }
            } else {
                source.sendError(Text.literal("§c玩家 $playerName 没有设置备用密码或临时账号"))
            }
        } else {
            // 设置新密码
            if (password.length < 4) {
                source.sendError(Text.literal("§c密码长度至少为4位"))
                return 0
            }
            
            val passwordHash = hashPassword(password)
            val success = if (isBound) {
                PlayerDataManager.setBackupPassword(targetUuid, passwordHash)
            } else if (hasTempAccount) {
                PlayerDataManager.updateTempPassword(targetUuid, passwordHash)
            } else {
                // 未绑定且无临时账号，创建临时账号
                PlayerDataManager.createTempAccount(targetUuid, passwordHash)
            }
            
            if (success) {
                val type = if (isBound) "备用密码" else "临时账号密码"
                source.sendFeedback({ Text.literal("§a已设置玩家 $playerName 的$type") }, true)
                Ohc_login.logger.info("管理员 ${source.name} 设置了玩家 $playerName 的$type")
                targetPlayer?.sendMessage(Text.literal("§e您的${type}已被管理员修改。").formatted(Formatting.YELLOW))
                
                // 如果玩家在线且通过备用登录，强制重新登录
                if (targetPlayer != null && LoginManager.isBackupLogged(targetUuid)) {
                    targetPlayer.sendMessage(Text.literal("§c您需要重新登录。").formatted(Formatting.RED))
                    LoginManager.forceRelogin(targetPlayer)
                }
            } else {
                source.sendError(Text.literal("§c设置密码失败"))
            }
        }
        
        return 1
    }
    
    /**
     * 执行存档命令
     */
    private fun executeOhcSave(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val backupName = StringArgumentType.getString(context, "backupName")
        val operatorName = source.name
        val server = source.server
        
        // 验证存档名（只允许字母数字下划线中文）
        if (!backupName.matches(Regex("^[\\w\\u4e00-\\u9fa5]+$"))) {
            source.sendError(Text.literal("§c存档名只能包含字母、数字、下划线和中文"))
            return 0
        }
        
        source.sendFeedback({ Text.literal("§e正在创建存档...") }, false)
        
        BackupManager.createBackup(server, backupName, operatorName).thenAccept { result ->
            server.execute {
                if (result.success) {
                    source.sendFeedback({ Text.literal("§a存档完成: ${result.backupName}") }, true)
                } else {
                    source.sendError(Text.literal("§c${result.message}"))
                }
            }
        }
        
        return 1
    }
    
    /**
     * 执行回档命令
     * @param worldType 可选：overworld/nether/end，null 表示全部恢复
     */
    private fun executeOhcRestore(context: CommandContext<ServerCommandSource>, worldType: String?): Int {
        val source = context.source
        val backupName = StringArgumentType.getString(context, "backupName")
        val operatorName = source.name
        val server = source.server
        
        // 检查存档是否存在
        if (!BackupManager.backupExists(backupName)) {
            // 尝试模糊匹配
            val backups = BackupManager.listBackups()
            val matched = backups.filter { it.name.startsWith(backupName) }
            
            when {
                matched.isEmpty() -> {
                    source.sendError(Text.literal("§c找不到存档: $backupName"))
                    source.sendFeedback({ Text.literal("§7输入 /ohcres 查看所有存档") }, false)
                }
                matched.size == 1 -> {
                    return executeRestoreWithName(source, server, matched[0].name, operatorName, worldType)
                }
                else -> {
                    source.sendFeedback({ Text.literal("§e匹配到 ${matched.size} 个存档，请输入更精确的名称（无需完整名称）:") }, false)
                    matched.take(5).forEach { backup ->
                        source.sendFeedback({ Text.literal("  §7${backup.name}") }, false)
                    }
                    if (matched.size > 5) {
                        source.sendFeedback({ Text.literal("  §8...还有 ${matched.size - 5} 个") }, false)
                    }
                }
            }
            return 0
        }
        
        return executeRestoreWithName(source, server, backupName, operatorName, worldType)
    }
    
    private fun executeRestoreWithName(
        source: ServerCommandSource,
        server: net.minecraft.server.MinecraftServer,
        backupName: String,
        operatorName: String,
        worldType: String?
    ): Int {
        val worldDesc = when (worldType) {
            "overworld" -> "主世界"
            "nether" -> "下界"
            "end" -> "末地"
            else -> "全部世界"
        }
        source.sendFeedback({ Text.literal("§c准备回档: $backupName ($worldDesc)") }, true)
        
        BackupManager.prepareRestore(server, backupName, operatorName, 10, worldType).thenAccept { result ->
            if (!result.success) {
                server.execute {
                    source.sendError(Text.literal("§c${result.message}"))
                }
            }
        }
        
        return 1
    }
    
    /**
     * 列出所有存档
     */
    private fun executeOhcRestoreList(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val backups = BackupManager.listBackups()
        
        if (backups.isEmpty()) {
            source.sendFeedback({ Text.literal("§e当前没有任何存档") }, false)
            source.sendFeedback({ Text.literal("§7使用 /ohcsave <名称> 创建存档") }, false)
            return 1
        }
        
        source.sendFeedback({ Text.literal("§6=== 存档列表 ===") }, false)
        
        val dateFormatter = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
        backups.forEach { backup ->
            val date = java.time.Instant.ofEpochMilli(backup.createdAt)
                .atZone(java.time.ZoneId.systemDefault())
                .format(dateFormatter)
            val size = formatBackupSize(backup.size)
            source.sendFeedback({ Text.literal("§a${backup.name} §7- $date §8($size)") }, false)
        }
        
        source.sendFeedback({ Text.literal("§6共 ${backups.size} 个存档") }, false)
        source.sendFeedback({ Text.literal("§7使用 /ohcres <存档名> 进行回档（无需完整名称）") }, false)
        
        return 1
    }
    
    private fun formatBackupSize(bytes: Long): String {
        return when {
            bytes >= 1024 * 1024 * 1024 -> String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024))
            bytes >= 1024 * 1024 -> String.format("%.2f MB", bytes / (1024.0 * 1024))
            bytes >= 1024 -> String.format("%.2f KB", bytes / 1024.0)
            else -> "$bytes B"
        }
    }
    
    /**
     * 执行删除存档命令
     */
    private fun executeOhcDelete(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val backupName = StringArgumentType.getString(context, "backupName")
        
        // 检查存档是否存在
        if (!BackupManager.backupExists(backupName)) {
            // 尝试模糊匹配
            val backups = BackupManager.listBackups()
            val matched = backups.filter { it.name.startsWith(backupName) }
            
            when {
                matched.isEmpty() -> {
                    source.sendError(Text.literal("§c找不到存档: $backupName"))
                    source.sendFeedback({ Text.literal("§7输入 /ohcres 查看所有存档") }, false)
                }
                matched.size == 1 -> {
                    return executeDeleteWithName(source, matched[0].name)
                }
                else -> {
                    source.sendFeedback({ Text.literal("§e匹配到 ${matched.size} 个存档，请输入更精确的名称(无需完整名称):") }, false)
                    matched.take(5).forEach { backup ->
                        source.sendFeedback({ Text.literal("  §7${backup.name}") }, false)
                    }
                }
            }
            return 0
        }
        
        return executeDeleteWithName(source, backupName)
    }
    
    private fun executeDeleteWithName(source: ServerCommandSource, backupName: String): Int {
        if (BackupManager.deleteBackup(backupName)) {
            source.sendFeedback({ Text.literal("§a已删除存档: $backupName") }, true)
            Ohc_login.logger.info("管理员 ${source.name} 删除了存档: $backupName")
        } else {
            source.sendError(Text.literal("§c删除存档失败: $backupName"))
        }
        return 1
    }
    
    /**
     * 执行授予存档权限命令
     */
    private fun executeOhcBackAdd(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val playerName = StringArgumentType.getString(context, "playerName")
        
        if (PlayerDataManager.hasBackupPermission(playerName)) {
            source.sendError(Text.literal("§c$playerName 已有存档权限"))
        } else {
            PlayerDataManager.grantBackupPermission(playerName)
            source.sendFeedback({ Text.literal("§a已授予 §f$playerName §a存档权限") }, true)
            Ohc_login.logger.info("管理员 ${source.name} 授予了 $playerName 存档权限")
        }
        return 1
    }
    
    /**
     * 执行撤销存档权限命令
     */
    private fun executeOhcBackDel(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val playerName = StringArgumentType.getString(context, "playerName")
        
        if (!PlayerDataManager.hasBackupPermission(playerName)) {
            source.sendError(Text.literal("§c$playerName 没有存档权限"))
        } else {
            PlayerDataManager.revokeBackupPermission(playerName)
            source.sendFeedback({ Text.literal("§c已撤销 §f$playerName §c的存档权限") }, true)
            Ohc_login.logger.info("管理员 ${source.name} 撤销了 $playerName 的存档权限")
        }
        return 1
    }
    
    /**
     * 列出所有有存档权限的玩家
     */
    private fun executeOhcBackList(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val list = PlayerDataManager.getBackupPermissionList()
        
        if (list.isEmpty()) {
            source.sendFeedback({ Text.literal("§e当前没有玩家被授予存档权限") }, false)
        } else {
            source.sendFeedback({ Text.literal("§6=== 存档权限列表 ===") }, false)
            list.forEach { name ->
                source.sendFeedback({ Text.literal("  §a$name") }, false)
            }
            source.sendFeedback({ Text.literal("§6共 ${list.size} 人") }, false)
        }
        source.sendFeedback({ Text.literal("§7使用 /ohcback <玩家名> 授予/撤销权限") }, false)
        return 1
    }
    
    /**
     * 查看自动存档状态
     */
    private fun executeOhcAutoStatus(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        source.sendFeedback({ Text.literal("§6=== 自动存档设置 ===") }, false)
        source.sendFeedback({ Text.literal(BackupManager.getAutoBackupStatus()) }, false)
        source.sendFeedback({ Text.literal("§7/ohcauto on|off - 开启/关闭") }, false)
        source.sendFeedback({ Text.literal("§7/ohcauto <时> <分> - 设置时间") }, false)
        return 1
    }
    
    /**
     * 开启/关闭自动存档
     */
    private fun executeOhcAutoToggle(context: CommandContext<ServerCommandSource>, enabled: Boolean): Int {
        val source = context.source
        val result = BackupManager.setAutoBackupEnabled(enabled)
        source.sendFeedback({ Text.literal(result) }, true)
        Ohc_login.logger.info("管理员 ${source.name} ${if (enabled) "开启" else "关闭"}了自动存档")
        return 1
    }
    
    /**
     * 设置自动存档时间
     */
    private fun executeOhcAutoSetTime(context: CommandContext<ServerCommandSource>): Int {
        val source = context.source
        val hour = com.mojang.brigadier.arguments.IntegerArgumentType.getInteger(context, "hour")
        val minute = com.mojang.brigadier.arguments.IntegerArgumentType.getInteger(context, "minute")
        val result = BackupManager.setAutoBackupTime(hour, minute)
        source.sendFeedback({ Text.literal(result) }, true)
        Ohc_login.logger.info("管理员 ${source.name} 设置自动存档时间为 ${String.format("%02d:%02d", hour, minute)}")
        return 1
    }
}
